/**
 
 @Name：layui.tree 树
 @Author：star1029
 @License：MIT

 */

layui.define('form', function(exports) {
    "use strict";

    var $ = layui.$,
        form = layui.form,
        layer = layui.layer

        //模块名
        ,MOD_NAME = 'tree'
        //外部接口
        ,tree = {
            config: {},
            index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0
            //设置全局项
           ,set: function(options) {
                var that = this;
                that.config = $.extend({}, that.config, options);
                return that;
            }
            //事件监听
            ,on: function(events, callback) {
                return layui.onevent.call(this, MOD_NAME, events, callback);
            }
        }

        //操作当前实例
        ,thisModule = function() {
            var that = this,
                options = that.config,
                id = options.id || that.index;

            thisModule.that[id] = that; //记录当前实例对象
            thisModule.config[id] = options; //记录当前实例配置项
            
            return {
                config: options //重置实例
                ,reload: function(options) {
                    that.reload.call(that, options);
                },
                getChecked: function() {
                    return that.getChecked.call(that);
                },
                setChecked: function(id) { //设置值
                    return that.setChecked.call(that, id);
                },
                getThisNode:function(){
                	return that.getThisNode.call(that);
                },
                getSelectedNode:function(){
                	return that.getSelectedNode.call(that);
                },
                getAllChildNodes:function(node){
                	return that.getAllChildNodes.call(that,node);
                },
                removeNode:function(node){
                	return that.removeNode.call(that,node);
                },
                addNode:function(newNode,node){
                	return that.addNode.call(that,newNode,node);
                },
                setNodeText:function(node,text){
                    return that.setNodeText.call(that,node,text);
                },
                selectNode:function(nodeId,value){
                    return that.selectNode.call(that,nodeId,value);
                },
            }
        }

        //获取当前实例配置项
        ,getThisModuleConfig = function(id) {
            var config = thisModule.config[id];
            if(!config) hint.error('The ID option was not found in the ' + MOD_NAME + ' instance');
            return config || null;
        }

        //字符常量
        ,SHOW = 'layui-show',
        HIDE = 'layui-hide',
        NONE = 'layui-none',
        DISABLED = 'layui-disabled',
        ELEM_VIEW = 'layui-tree',
        ELEM_SET = 'layui-tree-set',
        ICON_CLICK = 'layui-tree-iconClick',
        ICON_ADD = 'layui-icon-addition',
        ICON_SUB = 'layui-icon-subtraction',
        ELEM_ENTRY = 'layui-tree-entry',
        ELEM_MAIN = 'layui-tree-main',
        ELEM_TEXT = 'layui-tree-txt',
        ELEM_PACK = 'layui-tree-pack',
        ELEM_SPREAD = 'layui-tree-spread',
        ELEM_LINE_SHORT = 'layui-tree-setLineShort',
        ELEM_SHOW = 'layui-tree-showLine',
        ELEM_EXTEND = 'layui-tree-lineExtend'

        //构造器
        ,
        Class = function(options) {
            var that = this;
            that.index = ++tree.index;
            that.config = $.extend({}, that.config, tree.config, options);
            that.render();
        };

    //默认配置
    Class.prototype.config = {
        data: [] //数据
        ,showCheckbox: false //是否显示复选框
        ,showLine: false //是否开启连接线
        ,accordion: false //是否开启手风琴模式
        ,onlyIconControl: false //是否仅允许节点左侧图标控制展开收缩
        ,isJump: false //是否允许点击节点时弹出新窗口跳转
        ,edit: false, //是否开启节点的操作图标
        textField:"title", // 文本字段
        idField:"id",//id
        parentField:'pid',//父id
        param:{}, // 参数
        isList:false, //是否列表数据
        treeMenu:[],//下拉菜单
        showIcon:true,//是否显示图标
        expandNode:1,//默认展开的节点
        disableParentNode:false,//禁用父节点
        text: {
            defaultNodeName: '未命名' //节点默认名称
            ,none: '无数据' //数据为空时的文本提示
        }
    };

    //重载实例
    Class.prototype.reload = function(options) {
        var that = this;

        layui.each(options, function(key, item) {
            if(item.constructor === Array) delete that.config[key];
        });
        
        that.config = $.extend(true, {}, that.config, options);
        that.render();
    };
    
    //获取树结构数据
    Class.prototype.getTreeData = function(data,options) {
        var idField = options.idField , parentField = options.parentField;
        function getTree(data, pId) {
            var tree = [];
            for(var i = 0; i < data.length; i++) {
                if(data[i][parentField] == pId) {
                    data[i]['children'] = getTree(data, data[i][idField]);
                    tree.push(data[i]);
                }
            }
            return tree;
        }
        return  getTree(data, 0);
    };
    
    //主体渲染
    Class.prototype.render = function() {
        var that = this,
            options = that.config;
         
        that.checkids = [];

        var temp = $('<div class="layui-tree' + (options.showCheckbox ? " layui-form" : "") + (options.showLine ? " layui-tree-line" : "") + '" lay-filter="LAY-tree-' + that.index + '"></div>');
        that.tree(temp);

        var othis = options.elem = $(options.elem);
        if(!othis[0]) return;

        //索引
        that.key = options.id || that.index;

        //插入组件结构
        that.elem = temp;
        that.elemNone = $('<div class="layui-tree-emptyText">' + options.text.none + '</div>');
        othis.html(that.elem);
        if(that.elem.find('.layui-tree-set').length == 0) {
            return that.elem.append(that.elemNone);
        };

        //复选框渲染
        if(options.showCheckbox) {
            that.renderForm('checkbox');
        };

        that.elem.find('.layui-tree-set').each(function() {
            var othis = $(this);
            //最外层
            if(!othis.parent('.layui-tree-pack')[0]) {
                othis.addClass('layui-tree-setHide');
            };

            //没有下一个节点 上一层父级有延伸线
            if(!othis.next()[0] && othis.parents('.layui-tree-pack').eq(1).hasClass('layui-tree-lineExtend')) {
                othis.addClass(ELEM_LINE_SHORT);
            };

            //没有下一个节点 外层最后一个
            if(!othis.next()[0] && !othis.parents('.layui-tree-set').eq(0).next()[0]) {
                othis.addClass(ELEM_LINE_SHORT);
            };
        });

        that.events();
        setTimeout(function(){ 
            options.loadSuccess &&  options.loadSuccess( that.allData );
        },10);
    };

    //渲染表单
    Class.prototype.renderForm = function(type) {
        form.render(type, 'LAY-tree-' + this.index);
    };

    //节点解析
    Class.prototype.tree = function(elem, children, childrenIndex ) {
        childrenIndex = childrenIndex || 0;
        var that = this,
            options = that.config ,data = null;
            //wfs
            if(children){
                data = children;
            }else{
                data = options.data;
                if(typeof data == "string"){
                    $.ajaxs(data,options.param,function(res){
                        data = res.data; 
                    },false);
                }
                data = options.isList ? that.getTreeData( data ,options ) : data;
                that.allData = data[0] ? that.getAllChildNodes(data) : [];
            }
            //wfs - end
            
        //遍历数据
        layui.each(data, function(index, item) {
            //wfs - begin
            item._level = childrenIndex;
            item.spread = options.expandNode ? (options.expandNode > childrenIndex) : item.spread;
            //wfs - end
            var hasChild = item.children && item.children.length > 0,
                packDiv = $('<div class="layui-tree-pack" ' + (item.spread ? 'style="display: block;"' : '') + '"></div>'),
                entryDiv = $(['<div data-id="' + item[options.idField] + '" class="layui-tree-set' + (item.spread ? " layui-tree-spread" : "") + (item.checked ? " layui-tree-checkedFirst" : "") + '">', '<div class="layui-tree-entry">', '<div class="layui-tree-main">'
                    //箭头
                    ,
                    function() {
                        if(options.showLine) {
                            if(hasChild) {
                                return '<span class="layui-tree-iconClick layui-tree-icon"><i class="layui-icon ' + (item.spread ? "layui-icon-subtraction" : "layui-icon-addition") + '"></i></span>';
                            } else {
                                return '<span class="layui-tree-iconClick"><i class="layui-icon layui-icon-file"></i></span>';
                            };
                        } else {
                            return '<span class="layui-tree-iconClick"><i class="layui-tree-iconArrow ' + (hasChild ? "" : HIDE) + '"></i></span>';
                        };
                    }()
                    //复选框
                    ,
                    function() {
                        return options.showCheckbox ? '<input type="checkbox" name="' + (item.field || ('layuiTreeCheck_' +  item[options.idField])) + '" same="layuiTreeCheck" lay-skin="primary" ' + (item.disabled ? "disabled" : "") + ' value="' + item.id + '">' : '';
                    }() 
                    //图标
                    ,
					function (){
						if(!options.showIcon) return '';
						var s='<span class="iconfont">'
						if(typeof options.showIcon =='function'){
							s += options.showIcon(item) || '&#xe64c;';
						}else{
							s +=  '&#xe64c;';
						}
						s +=  '</span>';
						return s;
					}()
                    //节点
                    ,
                    function() {
                        if(options.isJump && item.href) {
                            return '<a href="' + item.href + '" target="_blank" class="' + ELEM_TEXT + '">' + (item.title || item.label || options.text.defaultNodeName) + '</a>';
                        } else {
                            return '<span class="' + ELEM_TEXT + (item.disabled ? ' ' + DISABLED : '') + '">' + ( item[options.textField] || item.label || options.text.defaultNodeName) + '</span>';
                        }
                    }(), '</div>'

                    //节点操作图标
                    ,
                    function() {
                        if(!options.edit) return '';

                        var editIcon = {
                                add: '<i class="layui-icon layui-icon-add-1"  data-type="add"></i>',
                                update: '<i class="layui-icon layui-icon-edit" data-type="update"></i>',
                                del: '<i class="layui-icon layui-icon-delete" data-type="del"></i>'
                            },
                            arr = ['<div class="layui-btn-group layui-tree-btnGroup">'];

                        if(options.edit === true) {
                            options.edit = ['update', 'del']
                        }

                        if(typeof options.edit === 'object') {
                            layui.each(options.edit, function(i, val) {
                                arr.push(editIcon[val] || '')
                            });
                            return arr.join('') + '</div>';
                        }
                    }(), 
                    function() {
                        if(!options.treeMenu.length) return '';
                        return '<div class="tree-more"><i class="iconfont icon-more"></i></div>';
                    }()
                    ,
                    '</div></div>'
                ].join(''));
			entryDiv.data('item',item);
            //如果有子节点，则递归继续生成树
            if(hasChild) {
                entryDiv.append(packDiv);
                that.tree(packDiv, item.children, childrenIndex ? (childrenIndex+1) : 1);
            };

            elem.append(entryDiv);

            //若有前置节点，前置节点加连接线
            if(entryDiv.prev('.' + ELEM_SET)[0]) {
                entryDiv.prev().children('.layui-tree-pack').addClass('layui-tree-showLine');
            };

            //若无子节点，则父节点加延伸线
            if(!hasChild) {
                entryDiv.parent('.layui-tree-pack').addClass('layui-tree-lineExtend');
            };
                
            //展开节点操作
            that.spread(entryDiv, item);

            //选择框
            if(options.showCheckbox) {
                item.checked && that.checkids.push(item.id);
                that.checkClick(entryDiv, item);
            }

            //操作节点
            options.edit && that.operate(entryDiv, item);

        });
    };

    //展开节点
    Class.prototype.spread = function(elem, item) {
        var that = this,
            options = that.config,
            entry = elem.children('.' + ELEM_ENTRY),
            elemMain = entry.children('.' + ELEM_MAIN),
            elemIcon = entry.find('.' + ICON_CLICK),
            elemText = entry.find('.' + ELEM_TEXT)
            //,touchOpen = options.onlyIconControl ? elemIcon : elemMain //判断展开通过节点还是箭头图标
            //wfs
            ,
            touchOpen = elemIcon //判断展开通过节点还是箭头图标
            ,
            state = '';

        //展开收缩
        touchOpen.on('click', spread);
        entry.on('dblclick', spread);
        function spread(e) {
            var packCont = elem.children('.' + ELEM_PACK),
                iconClick = touchOpen.children('.layui-icon')[0] ? touchOpen.children('.layui-icon') : touchOpen.find('.layui-tree-icon').children('.layui-icon');

            //若没有子节点
            if(!packCont[0]) {
                state = 'normal';
            } else {
                if(elem.hasClass(ELEM_SPREAD)) {
                    elem.removeClass(ELEM_SPREAD);
                    packCont.slideUp(200);
                    iconClick.removeClass(ICON_SUB).addClass(ICON_ADD);
                } else {
                    elem.addClass(ELEM_SPREAD);
                    packCont.slideDown(200);
                    iconClick.addClass(ICON_SUB).removeClass(ICON_ADD);

                    //是否手风琴
                    if(options.accordion) {
                        var sibls = elem.siblings('.' + ELEM_SET);
                        sibls.removeClass(ELEM_SPREAD);
                        sibls.children('.' + ELEM_PACK).slideUp(200);
                        sibls.find('.layui-tree-icon').children('.layui-icon').removeClass(ICON_SUB).addClass(ICON_ADD);
                    };
                };
            };
        }

        //点击回调
        entry.on('click', function(e) {
        	e.stopPropagation();
            var othis = $(this);

            //判断是否禁用状态
            if($(e.target).is('.layui-tree-iconArrow'))return;
            if($(e.target).is('.icon-more'))return;
            if(othis.hasClass(DISABLED)) return;
			if(options.disableParentNode && item.children.length!=0) return;
			
            //判断展开收缩状态
            if(elem.hasClass(ELEM_SPREAD)) {
                state = options.onlyIconControl ? 'open' : 'close';
            } else {
                state = options.onlyIconControl ? 'close' : 'open';
            }

            //wfs - 选中节点
            $(".layui-tree-selectedNode").removeClass("layui-tree-selectedNode");
            if(!options.showLine) {
                othis.addClass('layui-tree-selectedNode');
            } else {
                othis.find(".layui-tree-main").addClass('layui-tree-selectedNode');
            }
            
            //点击产生的回调
            options.click && options.click({ elem: elem, state: state,  data: item });
            options.selectedNode && options.selectedNode({ elem: elem, state: state,  data: item });
        });
        
        $(entry).find(".tree-more").unbind("click").click(function(e) {
            e.stopPropagation();
            var that = $(this);
            var timoutide=null;
            var top = $(this).offset().top;
        	$(".layui-tree_dropDown_menu").remove();
			var $ul = $("<ul class='layui-tree_dropDown_menu' ></ul>");
			$.each(options.treeMenu,function(index) {
				var flag = typeof this.enable =='function' ?  (this.enable(item) || false) : true;
				if(flag){
					$ul.append("<li  onclick='"+this.onClick+"'>"+this.title+"</li>");
				}
			});
			$("body").append($ul);
			if((window.innerHeight/2+30)<$(this).offset().top){  top=$(this).offset().top - $ul.innerHeight() - 10; }
            $ul.css({"left": $(this).offset().left - $ul.width() + 22,"top": top + 20});
			$(this).mouseout(function(){
				timoutide = setTimeout(function() { $ul.hide(); }, 10);
			});
            $ul.unbind("hover").hover(function(e) {
				clearInterval(timoutide);
				$(this).show();
				that.parents('.layui-tree-entry').addClass('hover');
			}, function() {
				$ul.hide(); 
				that.parents('.layui-tree-entry').removeClass('hover');
			});
        });
        
    };
	
    Class.prototype.getNode = function(node){
        var elem = null;
        $.each(this.elem.find('.layui-tree-set'), function(index) {
            if( JSON.stringify($(this).data('item')) == JSON.stringify(node) ){
                elem = $(this);
                return false;
            }
        });
        console.log(elem)
        return elem;
    }
	
	Class.prototype.getThisNode = function() {
		return this.elem.find('.layui-tree-entry.hover').parent().data('item');
	}
	
	Class.prototype.getSelectedNode = function() {
		return this.elem.find('.layui-tree-selectedNode').parents('.layui-tree-set').data('item');
	}
	
	Class.prototype.getAllChildNodes = function(node) {
		var data = node || this.getSelectedNode() || {};
		if( !$.isArray(data) ) data = [data];
		var arr = [];
		function recursion(data){
			$.each(data, function(index,obj) {
				arr.push(obj);
				if(obj.children && obj.children.length>0){
					recursion(obj.children);
				}
			});
			return arr;
		}
		return recursion(data);
	}
	
	Class.prototype.selectNode = function(nodeId,value) {
        var that = this, options = that.config, data= {};
        if(nodeId && value){
            $.each(that.allData, function(index,obj) {
                if(obj[nodeId] == value){
                    data = obj;
                    return false;
                }
            });
            this.elem.find('.layui-tree-selectedNode').removeClass('layui-tree-selectedNode');
            var elem = this.elem.find('.layui-tree-set[data-id="'+data[options.idField]+'"]')
            .find('>.layui-tree-entry');
            if(!options.showLine) {
                elem.addClass('layui-tree-selectedNode');
            } else {
                elem.find(".layui-tree-main").addClass('layui-tree-selectedNode');
            }
            options.selectedNode && options.selectedNode({ elem: elem, state: 'open',  data: data });
        }
    }
	
	Class.prototype.addNode = function(newNode,node,elem) {
	    var that=this,options = that.config;
	    if(newNode && node){
	        var elem = elem || this.getNode(node),
            entry = elem.children('.' + ELEM_ENTRY),
            elemMain = entry.children('.' + ELEM_MAIN),
            packCont = elem.children('.' + ELEM_PACK);
            //若节点本身无子节点
            if(!packCont[0]) {
                elemMain.find('.layui-tree-iconArrow').removeClass(HIDE);
                elem.append( $('<div class="layui-tree-pack"></div>').show() );
            };
            elem.addClass(ELEM_SPREAD);
            elem.find(".layui-tree-pack").show();
            that.tree(elem.children('.' + ELEM_PACK), [newNode]);
	    }
	}
	
	Class.prototype.removeNode = function(node) {
        var that = this, options = that.config;
        var elem = this.getNode(node),
        prevDiv = elem.parent('.' + ELEM_PACK).prev();
        if(elem.siblings().length==0){
            //父节点隐藏箭头
            prevDiv.find('.layui-tree-iconArrow').addClass(HIDE);
            //移除展开属性
            elem.parents('.' + ELEM_SET).eq(0).removeClass(ELEM_SPREAD);
            //移除节点容器
            elem.parent('.' + ELEM_PACK).remove();
        }
        elem.remove();
    }
    
    Class.prototype.setNodeText = function(node,text) {
        var that = this, options = that.config;
        var elem = this.getNode(node);
        var obj = elem.data('item'); obj[options.textField] = text;
        text && node && elem.find(".layui-tree-txt").text(text) && elem.data('item',obj);
    }
    
    
    //计算复选框选中状态
    Class.prototype.setCheckbox = function(elem, item, elemCheckbox) {
        var that = this,
            options = that.config,
            checked = elemCheckbox.prop('checked');

        if(elemCheckbox.prop('disabled')) return;

        //同步子节点选中状态
        if(typeof item.children === 'object' || elem.find('.' + ELEM_PACK)[0]) {
            var childs = elem.find('.' + ELEM_PACK).find('input[same="layuiTreeCheck"]');
            childs.each(function() {
                if(this.disabled) return; //不可点击则跳过
                this.checked = checked;
            });
        };

        //同步父节点选中状态
        var setParentsChecked = function(thisNodeElem) {
            //若无父节点，则终止递归
            if(!thisNodeElem.parents('.' + ELEM_SET)[0]) return;

            var state, parentPack = thisNodeElem.parent('.' + ELEM_PACK),
                parentNodeElem = parentPack.parent(),
                parentCheckbox = parentPack.prev().find('input[same="layuiTreeCheck"]');

            //如果子节点有任意一条选中，则父节点为选中状态
            if(checked) {
                parentCheckbox.prop('checked', checked);
            } else { //如果当前节点取消选中，则根据计算“兄弟和子孙”节点选中状态，来同步父节点选中状态
                parentPack.find('input[same="layuiTreeCheck"]').each(function() {
                    if(this.checked) {
                        state = true;
                    }
                });

                //如果兄弟子孙节点全部未选中，则父节点也应为非选中状态
                state || parentCheckbox.prop('checked', false);
            }

            //向父节点递归
            setParentsChecked(parentNodeElem);
        };

        setParentsChecked(elem);

        that.renderForm('checkbox');
    };

    //复选框选择
    Class.prototype.checkClick = function(elem, item) {
        var that = this,
            options = that.config,
            entry = elem.children('.' + ELEM_ENTRY),
            elemMain = entry.children('.' + ELEM_MAIN);

        //点击复选框
        elemMain.on('click', 'input[same="layuiTreeCheck"]+', function(e) {
            layui.stope(e); //阻止点击节点事件

            var elemCheckbox = $(this).prev(),
                checked = elemCheckbox.prop('checked');

            if(elemCheckbox.prop('disabled')) return;

            that.setCheckbox(elem, item, elemCheckbox);

            //复选框点击产生的回调
            options.oncheck && options.oncheck({
                elem: elem,
                checked: checked,
                data: item
            });
        });
    };

    //节点操作
    Class.prototype.operate = function(elem, item) {
        var that = this,
            options = that.config,
            entry = elem.children('.' + ELEM_ENTRY),
            elemMain = entry.children('.' + ELEM_MAIN);

        entry.children('.layui-tree-btnGroup').on('click', '.layui-icon', function(e) {
            layui.stope(e); //阻止节点操作

            var type = $(this).data("type"),
                packCont = elem.children('.' + ELEM_PACK),
                returnObj = {
                    data: item,
                    type: type,
                    elem: elem
                };
            //增加
            if(type == 'add') {
                //若节点本身无子节点
                if(!packCont[0]) {
                    //若开启连接线，更改图标样式
                    if(options.showLine) {
                        elemMain.find('.' + ICON_CLICK).addClass('layui-tree-icon');
                        elemMain.find('.' + ICON_CLICK).children('.layui-icon').addClass(ICON_ADD).removeClass('layui-icon-file');
                        //若未开启连接线，显示箭头
                    } else {
                        elemMain.find('.layui-tree-iconArrow').removeClass(HIDE);
                    };
                    //节点添加子节点容器
                    elem.append('<div class="layui-tree-pack"></div>');
                };

                //新增节点
                var key = options.operate && options.operate(returnObj),
                    obj = {};
                obj.title = options.text.defaultNodeName;
                obj.id = key;
                that.tree(elem.children('.' + ELEM_PACK), [obj]);

                //放在新增后面，因为要对元素进行操作
                if(options.showLine) {
                    //节点本身无子节点
                    if(!packCont[0]) {
                        //遍历兄弟节点，判断兄弟节点是否有子节点
                        var siblings = elem.siblings('.' + ELEM_SET),
                            num = 1,
                            parentPack = elem.parent('.' + ELEM_PACK);
                        layui.each(siblings, function(index, i) {
                            if(!$(i).children('.' + ELEM_PACK)[0]) {
                                num = 0;
                            };
                        });

                        //若兄弟节点都有子节点
                        if(num == 1) {
                            //兄弟节点添加连接线
                            siblings.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
                            siblings.children('.' + ELEM_PACK).children('.' + ELEM_SET).removeClass(ELEM_LINE_SHORT);
                            elem.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
                            //父级移除延伸线
                            parentPack.removeClass(ELEM_EXTEND);
                            //同层节点最后一个更改线的状态
                            parentPack.children('.' + ELEM_SET).last().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
                        } else {
                            elem.children('.' + ELEM_PACK).children('.' + ELEM_SET).addClass(ELEM_LINE_SHORT);
                        };
                    } else {
                        //添加延伸线
                        if(!packCont.hasClass(ELEM_EXTEND)) {
                            packCont.addClass(ELEM_EXTEND);
                        };
                        //子节点添加延伸线
                        elem.find('.' + ELEM_PACK).each(function() {
                            $(this).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
                        });
                        //如果前一个节点有延伸线
                        if(packCont.children('.' + ELEM_SET).last().prev().hasClass(ELEM_LINE_SHORT)) {
                            packCont.children('.' + ELEM_SET).last().prev().removeClass(ELEM_LINE_SHORT);
                        } else {
                            //若之前的没有，说明处于连接状态
                            packCont.children('.' + ELEM_SET).last().removeClass(ELEM_LINE_SHORT);
                        };
                        //若是最外层，要始终保持相连的状态
                        if(!elem.parent('.' + ELEM_PACK)[0] && elem.next()[0]) {
                            packCont.children('.' + ELEM_SET).last().removeClass(ELEM_LINE_SHORT);
                        };
                    };
                };
                if(!options.showCheckbox) return;
                //若开启复选框，同步新增节点状态
                if(elemMain.find('input[same="layuiTreeCheck"]')[0].checked) {
                    var packLast = elem.children('.' + ELEM_PACK).children('.' + ELEM_SET).last();
                    packLast.find('input[same="layuiTreeCheck"]')[0].checked = true;
                };
                that.renderForm('checkbox');

                //修改
            } else if(type == 'update') {
                var text = elemMain.children('.' + ELEM_TEXT).html();
                elemMain.children('.' + ELEM_TEXT).html('');
                //添加输入框，覆盖在文字上方
                elemMain.append('<input type="text" class="layui-tree-editInput">');
                //获取焦点
                elemMain.children('.layui-tree-editInput').val(text).focus();
                //嵌入文字移除输入框
                var getVal = function(input) {
                    var textNew = input.val().trim();
                    textNew = textNew ? textNew : options.text.defaultNodeName;
                    input.remove();
                    elemMain.children('.' + ELEM_TEXT).html(textNew);

                    //同步数据
                    returnObj.data.title = textNew;

                    //节点修改的回调
                    options.operate && options.operate(returnObj);
                };
                //失去焦点
                elemMain.children('.layui-tree-editInput').blur(function() {
                    getVal($(this));
                });
                //回车
                elemMain.children('.layui-tree-editInput').on('keydown', function(e) {
                    if(e.keyCode === 13) {
                        e.preventDefault();
                        getVal($(this));
                    };
                });

                //删除
            } else {
                layer.confirm('确认删除该节点 "<span style="color: #999;">' + (item.title || '') + '</span>" 吗？', function(index) {
                    options.operate && options.operate(returnObj); //节点删除的回调
                    returnObj.status = 'remove'; //标注节点删除

                    layer.close(index);

                    //若删除最后一个，显示空数据提示
                    if(!elem.prev('.' + ELEM_SET)[0] && !elem.next('.' + ELEM_SET)[0] && !elem.parent('.' + ELEM_PACK)[0]) {
                        elem.remove();
                        that.elem.append(that.elemNone);
                        return;
                    };
                    //若有兄弟节点
                    if(elem.siblings('.' + ELEM_SET).children('.' + ELEM_ENTRY)[0]) {
                        //若开启复选框
                        if(options.showCheckbox) {
                            //若开启复选框，进行下步操作
                            var elemDel = function(elem) {
                                //若无父结点，则不执行
                                if(!elem.parents('.' + ELEM_SET)[0]) return;
                                var siblingTree = elem.siblings('.' + ELEM_SET).children('.' + ELEM_ENTRY),
                                    parentTree = elem.parent('.' + ELEM_PACK).prev(),
                                    checkState = parentTree.find('input[same="layuiTreeCheck"]')[0],
                                    state = 1,
                                    num = 0;
                                //若父节点未勾选
                                if(checkState.checked == false) {
                                    //遍历兄弟节点
                                    siblingTree.each(function(i, item1) {
                                        var input = $(item1).find('input[same="layuiTreeCheck"]')[0]
                                        if(input.checked == false && !input.disabled) {
                                            state = 0;
                                        };
                                        //判断是否全为不可勾选框
                                        if(!input.disabled) {
                                            num = 1;
                                        };
                                    });
                                    //若有可勾选选择框并且已勾选
                                    if(state == 1 && num == 1) {
                                        //勾选父节点
                                        checkState.checked = true;
                                        that.renderForm('checkbox');
                                        //向上遍历祖先节点
                                        elemDel(parentTree.parent('.' + ELEM_SET));
                                    };
                                };
                            };
                            elemDel(elem);
                        };
                        //若开启连接线
                        if(options.showLine) {
                            //遍历兄弟节点，判断兄弟节点是否有子节点
                            var siblings = elem.siblings('.' + ELEM_SET),
                                num = 1,
                                parentPack = elem.parent('.' + ELEM_PACK);
                            layui.each(siblings, function(index, i) {
                                if(!$(i).children('.' + ELEM_PACK)[0]) {
                                    num = 0;
                                };
                            });
                            //若兄弟节点都有子节点
                            if(num == 1) {
                                //若节点本身无子节点
                                if(!packCont[0]) {
                                    //父级去除延伸线，因为此时子节点里没有空节点
                                    parentPack.removeClass(ELEM_EXTEND);
                                    siblings.children('.' + ELEM_PACK).addClass(ELEM_SHOW);
                                    siblings.children('.' + ELEM_PACK).children('.' + ELEM_SET).removeClass(ELEM_LINE_SHORT);
                                };
                                //若为最后一个节点
                                if(!elem.next()[0]) {
                                    elem.prev().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
                                } else {
                                    parentPack.children('.' + ELEM_SET).last().children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
                                };
                                //若为最外层最后一个节点，去除前一个结点的连接线
                                if(!elem.next()[0] && !elem.parents('.' + ELEM_SET)[1] && !elem.parents('.' + ELEM_SET).eq(0).next()[0]) {
                                    elem.prev('.' + ELEM_SET).addClass(ELEM_LINE_SHORT);
                                };
                            } else {
                                //若为最后一个节点且有延伸线
                                if(!elem.next()[0] && elem.hasClass(ELEM_LINE_SHORT)) {
                                    elem.prev().addClass(ELEM_LINE_SHORT);
                                };
                            };
                        };

                    } else {
                        //若无兄弟节点
                        var prevDiv = elem.parent('.' + ELEM_PACK).prev();
                        //若开启了连接线
                        if(options.showLine) {
                            prevDiv.find('.' + ICON_CLICK).removeClass('layui-tree-icon');
                            prevDiv.find('.' + ICON_CLICK).children('.layui-icon').removeClass(ICON_SUB).addClass('layui-icon-file');
                            //父节点所在层添加延伸线
                            var pare = prevDiv.parents('.' + ELEM_PACK).eq(0);
                            pare.addClass(ELEM_EXTEND);

                            //兄弟节点最后子节点添加延伸线
                            pare.children('.' + ELEM_SET).each(function() {
                                $(this).children('.' + ELEM_PACK).children('.' + ELEM_SET).last().addClass(ELEM_LINE_SHORT);
                            });
                        } else {
                            //父节点隐藏箭头
                            prevDiv.find('.layui-tree-iconArrow').addClass(HIDE);
                        };
                        //移除展开属性
                        elem.parents('.' + ELEM_SET).eq(0).removeClass(ELEM_SPREAD);
                        //移除节点容器
                        elem.parent('.' + ELEM_PACK).remove();
                    };

                    elem.remove();
                });

            };
        });
    };

    //部分事件
    Class.prototype.events = function() {
        var that = this,
            options = that.config,
            checkWarp = that.elem.find('.layui-tree-checkedFirst');

        //初始选中
        that.setChecked(that.checkids);

        //搜索
        that.elem.find('.layui-tree-search').on('keyup', function() {
            var input = $(this),
                val = input.val(),
                pack = input.nextAll(),
                arr = [];

            //遍历所有的值
            pack.find('.' + ELEM_TEXT).each(function() {
                var entry = $(this).parents('.' + ELEM_ENTRY);
                //若值匹配，加一个类以作标识
                if($(this).html().indexOf(val) != -1) {
                    arr.push($(this).parent());

                    var select = function(div) {
                        div.addClass('layui-tree-searchShow');
                        //向上父节点渲染
                        if(div.parent('.' + ELEM_PACK)[0]) {
                            select(div.parent('.' + ELEM_PACK).parent('.' + ELEM_SET));
                        };
                    };
                    select(entry.parent('.' + ELEM_SET));
                };
            });

            //根据标志剔除
            pack.find('.' + ELEM_ENTRY).each(function() {
                var parent = $(this).parent('.' + ELEM_SET);
                if(!parent.hasClass('layui-tree-searchShow')) {
                    parent.addClass(HIDE);
                };
            });
            if(pack.find('.layui-tree-searchShow').length == 0) {
                that.elem.append(that.elemNone);
            };

            //节点过滤的回调
            options.onsearch && options.onsearch({
                elem: arr
            });
        });

        //还原搜索初始状态
        that.elem.find('.layui-tree-search').on('keydown', function() {
            $(this).nextAll().find('.' + ELEM_ENTRY).each(function() {
                var parent = $(this).parent('.' + ELEM_SET);
                parent.removeClass('layui-tree-searchShow ' + HIDE);
            });
            if($('.layui-tree-emptyText')[0]) $('.layui-tree-emptyText').remove();
        });
    };

    //得到选中节点
    Class.prototype.getChecked = function() {
        var checkData = [];

        //遍历节点找到选中索引
        this.elem.find('.layui-form-checked').each(function() {
            checkData.push($(this).parents('.layui-tree-set').data('item'));
        });
        
        return checkData;
    };

    //设置选中节点
    Class.prototype.setChecked = function(checkedId) {
        var that = this,
            options = that.config;

        //初始选中
        that.elem.find('.' + ELEM_SET).each(function(i, item) {
            var thisId = $(this).data('id'),
                input = $(item).children('.' + ELEM_ENTRY).find('input[same="layuiTreeCheck"]'),
                reInput = input.next();

            //若返回数字
            if(typeof checkedId === 'number') {
                if(thisId == checkedId) {
                    if(!input[0].checked) {
                        reInput.click();
                    };
                    return false;
                };
            }
            //若返回数组
            else if(typeof checkedId === 'object') {
                layui.each(checkedId, function(index, value) {
                    if(value == thisId && !input[0].checked) {
                        reInput.click();
                        return true;
                    }
                });
            };
        });
    };

    //记录所有实例
    thisModule.that = {}; //记录所有实例对象
    thisModule.config = {}; //记录所有实例配置项

    //重载实例
    tree.reload = function(id, options) {
        var that = thisModule.that[id];
        that.reload(options);

        return thisModule.call(that);
    };
	
    //获得选中的节点数据
    tree.getChecked = function(id) {
        var that = thisModule.that[id];
        return that.getChecked();
    };

    //设置选中节点
    tree.setChecked = function(id, checkedId) {
        var that = thisModule.that[id];
        return that.setChecked(checkedId);
    };
	
	tree.getThisNode = function(id) {
        var that = thisModule.that[id];
        return that.getThisNode();
    };
    
    tree.getSelectedNode = function(id) {
        var that = thisModule.that[id];
        return that.getSelectedNode();
    };
	
	tree.getAllChildNodes = function(id,node) {
        var that = thisModule.that[id];
        return that.getAllChildNodes(node);
    };
    
    tree.removeNode = function(id,node) {
        var that = thisModule.that[id];
        return that.removeNode(node);
    };
    
    tree.addNode = function(id,newNode,node) {
        var that = thisModule.that[id];
        return that.addNode(newNode,node);
    };
    
    tree.setNodeText = function(id,node,text) {
        var that = thisModule.that[id];
        return that.setNodeText(node,text);
    };
    
    tree.selectNode = function(id,nodeId,value) {
        var that = thisModule.that[id];
        return that.selectNode(nodeId,value);
    };
    
    
    //核心入口
    tree.render = function(options) {
        var inst = new Class(options);
        return thisModule.call(inst);
    };
	
    exports(MOD_NAME, tree);
})